package com.bobo.jdk.aLambda;

import com.bobo.jdk.aLambda.domain.Person;
import com.bobo.jdk.aLambda.service.OrderService;
import com.bobo.jdk.aLambda.service.StudentService;
import com.bobo.jdk.aLambda.service.UserService;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Lambda 使用条件：1）接口方法  2. 接口中有且仅有一个抽象方法(@FunctionalInterface)
 *
 * 1.无参无返回值的 Lambda
 * 2.有参有返回值的 Lambda
 * 3.限定接口只能声明一个抽象方法
 * 4.内部类、Lambda得原理
 * 5.Lambda表达式省略写法
 *
 * 例1：无参无返回值的Lambda--创建线程
 * 例2：无参无返回值的Lambda--实现自定义接口
 * 例3：有参有返回值的Lambda--实现Collection.sort()
 * 例4：（无代码）内部类原理：编译时生成实现类.class；
 *              Lambda原理：运行时动态生成.class
 * 例5：省略参数类型、小括号、大括号的情况
 *
 */
public class LambdaDemo{

    public static void main(String[] args) {
        //example1();
        //example2();
        example3();
        example5();
    }
    
    //例 1：无参无返回值的Lambda--创建线程
    private static void example1(){
        //非lambda：创建线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("新线程中执行的代码 : "+Thread.currentThread().getName());
            }
        }).start();
        System.out.println("主线程中的代码：" + Thread.currentThread().getName());
        System.out.println("---------------");
    
        //aLambda：创建线程
        new Thread(
                () -> { System.out.println("新线程Lambda表达式..." +Thread.currentThread().getName()); }
        ).start();
    }
    
    //例 2：无参无返回值的Lambda--实现自定义接口
    private static void example2(){
        /*goShow(new UserService() {
            @Override
            public void show() {
                System.out.println("show 方法执行了...");
            }
        });
        System.out.println("----------");*/
        goShow(() -> {
            System.out.println("Lambda show 方法执行了...");
        });
    }
    
    private static void goShow(UserService userService){
        userService.show();
    }
    
    //例 3：有参有返回值的Lambda--实现自定义接口
    private static void example3(){
        List<Person> list = new ArrayList<>();
        list.add(new Person("周杰伦",33,175));
        list.add(new Person("刘德华",43,185));
        list.add(new Person("周星驰",38,177));
        list.add(new Person("郭富城",23,170));

        /*Collections.sort(list, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getAge()-o2.getAge();
            }
        });
        for (Person person : list) {
            System.out.println(person);
        }*/
        System.out.println("------");
        Collections.sort(list,(Person o1,Person o2) -> {
            return o1.getAge() - o2.getAge();
        });
        for (Person person : list) {
            System.out.println(person);
        }
    }
    
    //例 5：省略参数类型、小括号、大括号的情况
    private static void example5(){
        //无省略
        goStudent((String name,Integer age)->{ return name+age+" 6666 ..."; });
        //省略参数类型
        goStudent((name,age)-> name+age+" 6666 ...");
        //省略小括号：仅有一个参数
        goOrder(name -> { System.out.println("--->" + name); return 666; });
        //省略大括号：大括号内有且仅有一个语句，可以同时省略大括号，return 关键字及语句分号。
        goOrder(name -> 666);
    }
    
    private static void goStudent(StudentService studentService){
        studentService.show("张三",22);
    }
    private static void goOrder(OrderService orderService){
        orderService.show("李四");
    }
}
